package cc.admin.modules.sys.service.impl;

import cc.admin.common.constant.CommonConstant;
import cc.admin.common.constant.WebsocketConst;
import cc.admin.common.sys.vo.LoginUser;
import cc.admin.common.util.oConvertUtils;
import cc.admin.modules.message.websocket.WebSocket;
import cc.admin.modules.sys.entity.SysAnnouncement;
import cc.admin.modules.sys.entity.SysAnnouncementSend;
import cc.admin.modules.sys.entity.SysUser;
import cc.admin.modules.sys.entity.SystemMessage;
import cc.admin.modules.sys.mapper.SysAnnouncementMapper;
import cc.admin.modules.sys.mapper.SysAnnouncementSendMapper;
import cc.admin.modules.sys.mapper.SysUserMapper;
import cc.admin.modules.sys.mapper.SystemMessageMapper;
import cc.admin.modules.sys.service.ISysAnnouncementService;
import cc.admin.modules.sys.service.ISysUserService;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Description: 系统通告表
 * @Author: jeecg-boot
 * @Date: 2019-01-02
 * @Version: V1.0
 */
@Service
public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMapper, SysAnnouncement> implements ISysAnnouncementService {

	@Resource
	private SysAnnouncementMapper sysAnnouncementMapper;

	@Resource
	private SysAnnouncementSendMapper sysAnnouncementSendMapper;

	@Resource
	private ISysUserService sysUserService;
	@Resource
	private SysUserMapper sysUserMapper;

	@Resource
	private SystemMessageMapper systemMessageMapper;
	@Resource
	private WebSocket webSocket;

	@Transactional
	@Override
	public void saveAnnouncement(SysAnnouncement sysAnnouncement) {
		if (sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_ALL)) {
			sysAnnouncementMapper.insert(sysAnnouncement);
		} else {
			// 1.插入通告表记录
			sysAnnouncementMapper.insert(sysAnnouncement);
			// 2.插入用户通告阅读标记表记录
			String userId = sysAnnouncement.getUserIds();
			if (StrUtil.isNotEmpty(userId)) {
				String[] userIds = userId.split(",");
				String anntId = sysAnnouncement.getId();
				for (int i = 0; i < userIds.length; i++) {
					SysAnnouncementSend announcementSend = new SysAnnouncementSend();
					announcementSend.setAnntId(anntId);
					announcementSend.setUserId(userIds[i]);
					announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
					sysAnnouncementSendMapper.insert(announcementSend);
				}
			}
		}
	}

	/**
	 * @功能：编辑消息信息
	 */
	@Transactional
	@Override
	public boolean upDateAnnouncement(SysAnnouncement sysAnnouncement) {
		// 1.更新系统信息表数据
		sysAnnouncementMapper.updateById(sysAnnouncement);
		String userId = sysAnnouncement.getUserIds();
		if (oConvertUtils.isNotEmpty(userId) && sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_UESR)) {
			// 2.补充新的通知用户数据
			String[] userIds = userId.substring(0, (userId.length())).split(",");
			String anntId = sysAnnouncement.getId();
			Date refDate = new Date();
			for (int i = 0; i < userIds.length; i++) {
				LambdaQueryWrapper<SysAnnouncementSend> queryWrapper = new LambdaQueryWrapper<SysAnnouncementSend>();
				queryWrapper.eq(SysAnnouncementSend::getAnntId, anntId);
				queryWrapper.eq(SysAnnouncementSend::getUserId, userIds[i]);
				List<SysAnnouncementSend> announcementSends = sysAnnouncementSendMapper.selectList(queryWrapper);
				if (announcementSends.size() <= 0) {
					SysAnnouncementSend announcementSend = new SysAnnouncementSend();
					announcementSend.setAnntId(anntId);
					announcementSend.setUserId(userIds[i]);
					announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
					sysAnnouncementSendMapper.insert(announcementSend);
				}
			}
			// 3. 删除多余通知用户数据
			Collection<String> delUserIds = Arrays.asList(userIds);
			LambdaQueryWrapper<SysAnnouncementSend> queryWrapper = new LambdaQueryWrapper<SysAnnouncementSend>();
			queryWrapper.notIn(SysAnnouncementSend::getUserId, delUserIds);
			queryWrapper.eq(SysAnnouncementSend::getAnntId, anntId);
			sysAnnouncementSendMapper.delete(queryWrapper);
		}
		return true;
	}

	// @功能：流程执行完成保存消息通知
	@Override
	public void saveSysAnnouncement(String title, String msgContent) {
		SysAnnouncement announcement = new SysAnnouncement();
		announcement.setTitle(title);
		announcement.setMsgContent(msgContent);
		announcement.setSender("CC-ADMIN BOOT");
		announcement.setPriority(CommonConstant.PRIORITY_L);
		announcement.setMsgType(CommonConstant.MSG_TYPE_ALL);
		announcement.setSendStatus(CommonConstant.HAS_SEND);
		announcement.setSendTime(new Date());
		announcement.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
		sysAnnouncementMapper.insert(announcement);
	}

	@Override
	public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory) {
		return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(page, userId, msgCategory));
	}

	@Override
	public Page<SysAnnouncement> queryMessagePageByUserId(Page<SysAnnouncement> page, String userId) {
		return page.setRecords(sysAnnouncementMapper.queryMessageListByUserId(page, userId));
	}

	@Override
	public void readTheMessage(SysAnnouncement sysAnnouncement) {
//		获取当前登录人
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		String userId = sysUser.getId();

		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("annt_id", sysAnnouncement.getId());
		queryWrapper.eq("user_id", userId);
		List<SysAnnouncementSend>sysAnnouncementSends=sysAnnouncementSendMapper.selectList(queryWrapper);

		if(sysAnnouncementSends!=null && sysAnnouncementSends.size()>0){
			for (SysAnnouncementSend sysAnnouncementSend:sysAnnouncementSends){
				sysAnnouncementSend.setReadFlag("1");
				sysAnnouncementSend.setReadTime(new Date());
				sysAnnouncementSendMapper.updateById(sysAnnouncementSend);
			}
		}else {
			SysAnnouncementSend send = new SysAnnouncementSend();
			send.setAnntId(sysAnnouncement.getId());
			send.setUserId(userId);
			send.setReadFlag("1");
			send.setReadTime(new Date());
			sysAnnouncementSendMapper.insert(send);
		}

	}

	@Override
	public void batchProcessingRead(String [] list) {
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		String userId = sysUser.getId();
		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("user_id", userId);
		List<SysAnnouncementSend> sends =sysAnnouncementSendMapper.selectList(queryWrapper);
		for (SysAnnouncementSend send:sends){
			send.setReadFlag("1");
			send.setReadTime(new Date());
			sysAnnouncementSendMapper.updateById(send);
		}
	}

	@Override
	public void flowTheMessage(Map<String, Object> flowData) {
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		SysAnnouncementSend send = new SysAnnouncementSend();
		send.setAnntId(flowData.get("id").toString());
		send.setUserId(sysUser.getId());
		send.setReadFlag("1");
		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("annt_id", flowData.get("id").toString());
		queryWrapper.eq("user_id",sysUser.getId());
		Long num=sysAnnouncementSendMapper.selectCount(queryWrapper);
		if (num<=0){
			sysAnnouncementSendMapper.insert(send);
		}
	}

	@Override
	public void saveSystemMessage(String[] userIds, SysAnnouncement sysAnnouncement) {
		if (userIds.length>0){
			for (String id:userIds){
				SysUser sysUser = sysUserService.getById(id);
				SystemMessage systemMessage = new SystemMessage();
				systemMessage.setMessageHeader(sysAnnouncement.getTitle());
				systemMessage.setMessageContent(sysAnnouncement.getMsgContent());
				systemMessage.setMessageType(sysAnnouncement.getMsgType());
				systemMessage.setAnnouncementId(sysAnnouncement.getId());
				systemMessage.setSendTime(sysAnnouncement.getSendTime());
				systemMessage.setSender(sysAnnouncement.getSender());
				systemMessage.setSenderName(sysAnnouncement.getSenderName());
				systemMessage.setUserId(sysUser.getId());
				systemMessage.setUserName(sysUser.getRealname());
				systemMessageMapper.insert(systemMessage);
			}
		}
	}

	@Override
	public void saveAllSystemMessage(SysAnnouncement sysAnnouncement) {
		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("del_flag", 0);
//   获取总数
		Long totalCount =sysUserMapper.selectCount(queryWrapper);
		Integer batchSizeLimit=10;
		List<Map<String,Integer>> pageDTOList = getPageLimitGroupList(totalCount, batchSizeLimit);
		if (!CollectionUtils.isEmpty(pageDTOList)){
			for (Map<String,Integer> dto:pageDTOList){
				List<SysUser> sysUsers=sysUserService.getUserPageList(dto.get("currIndex"),dto.get("pageSize"));
				if (sysUsers.size()>0){
					for (SysUser sysUser:sysUsers){
						SystemMessage systemMessage = new SystemMessage();
						systemMessage.setMessageHeader(sysAnnouncement.getTitle());
						systemMessage.setMessageContent(sysAnnouncement.getMsgContent());
						systemMessage.setMessageType(sysAnnouncement.getMsgType());
						systemMessage.setAnnouncementId(sysAnnouncement.getId());
						systemMessage.setSendTime(sysAnnouncement.getSendTime());
						systemMessage.setSender(sysAnnouncement.getSender());
						systemMessage.setSenderName(sysAnnouncement.getSenderName());
						systemMessage.setUserId(sysUser.getId());
						systemMessage.setUserName(sysUser.getRealname());
						systemMessageMapper.insert(systemMessage);
					}
				}
			}
		}


	}

	@Override
	public void batchRead(String [] ids) {
		LoginUser sysUser=(LoginUser)SecurityUtils.getSubject().getPrincipal();
		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("user_id", sysUser.getId());
		queryWrapper.eq("read_flag", "0");
		if (ids.length>0){
			queryWrapper.in("annt_id", ids);
		}
		List<SysAnnouncementSend>sysAnnouncementSends=sysAnnouncementSendMapper.selectList(queryWrapper);
		for (SysAnnouncementSend send:sysAnnouncementSends){
			send.setReadFlag("1");
			sysAnnouncementSendMapper.updateById(send);
		}
		JSONObject obj = new JSONObject();
		obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_READ);
		obj.put(WebsocketConst.MSG_ID, " ");
		obj.put(WebsocketConst.MSG_TXT, "");
		webSocket.sendAllMessage(obj.toJSONString());
	}

	@Override
	public Long getAnnouncementCount() {
		LoginUser sysUser=(LoginUser) SecurityUtils.getSubject().getPrincipal();
		QueryWrapper<SysAnnouncement> queryWrapper3 = new QueryWrapper<>();
		queryWrapper3.eq("send_status", "publish");
		queryWrapper3.eq("del_flag", "0");
		if ("1".equals(sysUser.getIsProxy())) {
			queryWrapper3.apply("id IN ( select annt_id from sys_announcement_send where read_flag = {0})", "0");
		} else {
			queryWrapper3.apply("id IN ( select annt_id from sys_announcement_send where user_id = {0} and read_flag = {1})", sysUser.getId(), "0");
		}
		Long message = sysAnnouncementMapper.selectCount(queryWrapper3);
		return message;
	}

	@Override
	public void popupMessage(SysAnnouncement sysAnnouncement) {
		if (sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_ALL)) {
			JSONObject obj = new JSONObject();
			obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
			obj.put(WebsocketConst.MSG_ID, sysAnnouncement.getId());
			obj.put(WebsocketConst.MSG_TXT, JSONObject.toJSON(sysAnnouncement));
			saveAllSystemMessage(sysAnnouncement);
			webSocket.sendAllMessage(obj.toJSONString());
		} else {
			// 2.插入用户通告阅读标记表记录
			String userId = sysAnnouncement.getUserIds();
			String[] userIds = StrUtil.split(userId, ",");
			String anntId = sysAnnouncement.getId();
			Date refDate = new Date();
			JSONObject obj = new JSONObject();
			obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
			obj.put(WebsocketConst.MSG_ID, sysAnnouncement.getId());
			obj.put(WebsocketConst.MSG_TXT, JSONObject.toJSON(sysAnnouncement));
			saveSystemMessage(userIds,sysAnnouncement);
			webSocket.sendMoreMessage(userIds, obj.toJSONString());

		}
	}

	private List<Map<String,Integer>> getPageLimitGroupList(Long totalCount, Integer batchSizeLimit) {
		long pageNum = totalCount / batchSizeLimit;
		long surplus = totalCount % batchSizeLimit;
		if (surplus > 0) {
			pageNum = pageNum + 1;
		}
		List<Map<String,Integer>> pageList = new LinkedList<>();
		for (int i=0;i<pageNum;i++){
			Integer currIndex = i * batchSizeLimit;
			Map<String,Integer> pageMap= Maps.newHashMap();
			pageMap.put("pageSize",batchSizeLimit);
			pageMap.put("currIndex",currIndex);
			pageMap.put("dealDataCount", currIndex+batchSizeLimit);
			pageList.add(pageMap);
		}
		return pageList;
	}

}
